package util;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import enums.AdapterEnum;
import enums.CompositeEnum;
import enums.DecoratorEnum;

public class PatternXMLParser extends PatternParser {
	
	public PatternXMLParser(){
		super();
	}
	
	public Map<String,Set<Enum>> parse(String... filenames) throws DocumentException, ClassNotFoundException{
		
		SAXReader reader = new SAXReader();
		for(String filename :filenames){
			File file = new File(filename);
			Document document = reader.read(file);
			Element root = document.getRootElement();
			List<Element> children = root.elements();
			//children are patterns
			for(Element child : children){
				String className;
				switch(child.attributeValue("name")){
				case "Adapter":   parseAdapterPattern(child); break;
				case "Decorator": parseDecoratorPattern(child); break;
				case "Composite": parseCompositePattern(child); break;
				default: throw new RuntimeException("Unexpected Pattern Type");
				}
				
				
			}
		}
		
		return patternTypeMap;
	}
	
	private void parseCompositePattern(Element child) {
		List<Element> roles = child.elements();
		for(Element role : roles){
			Enum patternType;				
			switch(role.attributeValue("name")){
			case "Component": patternType = CompositeEnum.Component; break;
			case "Composite": patternType = CompositeEnum.Composite; break;
			case "Leaf": patternType = CompositeEnum.Leaf; break;
			default: throw new RuntimeException("Unexpected decorator pattern role");
			}
			for(Element roleInstance : role.elements()){
				String name = roleInstance.attributeValue("name");
				addPatternType(name,patternType);
			}
		}
		
	}

	private void parseDecoratorPattern(Element child) {
		List<Element> roles = child.elements();
		for(Element role : roles){
			Enum patternType;	
			switch(role.attributeValue("name")){
			case "Component": patternType = DecoratorEnum.Component; break;
			case "ConcreteComponent": patternType = DecoratorEnum.ConcreteComponent; break;
			case "Decorator": patternType = DecoratorEnum.Decorator; break;
			case "ConcreteDecorator": patternType = DecoratorEnum.ConcreteDecorator; break;
			default: throw new RuntimeException("Unexpected decorator pattern role");
			}
			//there may be several roles as the childeren of role - i.e. several Classes playing the same role
			
			for(Element roleInstance : role.elements()){
				String name = roleInstance.attributeValue("name");
				super.addPatternType(name,patternType);
			}
			
		}
		
	}

	private void parseAdapterPattern(Element child) {
		List<Element> roles = child.elements();
		for(Element role : roles){
			Enum patternType;				
			switch(role.attributeValue("name")){
			case "Target": patternType = AdapterEnum.Target; break;
			case "Adapter":patternType = AdapterEnum.Adapter; break;
			case "Adaptee":patternType = AdapterEnum.Adaptee; break;
			default: throw new RuntimeException("Unexpected adapter pattern role");
			}
			for(Element roleInstance : role.elements()){
				String name = roleInstance.attributeValue("name");
				super.addPatternType(name,patternType);
			}
		}
		
	}

	
	
	
}
